package cz.boxdesign.library.umgr.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import cz.boxdesign.library.common.dao.DatabaseOperationException;
import cz.boxdesign.library.service.UserService;

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

  public static final GrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER");
  public static final GrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");

  @Autowired
  private UserService userService;

  @Autowired
  private UserServiceAssembler assembler;

  @Override
  @Transactional(readOnly = true, isolation = Isolation.READ_COMMITTED)
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
    try {
      List<cz.boxdesign.library.entity.User> userList = userService.getByClause("and login_u = '" + username + "'");
      if (userList.isEmpty()) {
        throw new UsernameNotFoundException("Username is Incorrect ! Username '" + username + "' does not exist");
      }
      cz.boxdesign.library.entity.User user = userList.get(0);
      return assembler.buildAuthenticatedUserDTOFromUser(convertUser(user), user.getJmeno() + " " + user.getPrijmeni(), user.getId().toString());
    } catch (DatabaseOperationException e) {
      throw new UsernameNotFoundException(e.getLocalizedMessage());
    }
  }

  private User convertUser(cz.boxdesign.library.entity.User user) throws DatabaseOperationException {
    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    if (user.isAdmin()) {
      authorities.add(ROLE_ADMIN);
    }
    authorities.add(ROLE_USER);

    return new User(user.getLogin(), user.getPassword(), true, !userService.isAccountExpired(user.getId()), true, true, authorities);
  }

}
